package app.species.ANN;

import ec.util.MersenneTwisterFast;
import java.io.*;
import java.util.StringTokenizer;

import app.species.Mutable;
import app.species.SpeciesSim;

public class AdamBrain extends Brain{

	/**
	 * 
	 */
	private static final long serialVersionUID = 7869299136562795828L;

	public AdamBrain(SomaChromosome sChrome, AxonChromosome aChrome, MersenneTwisterFast random){
		super(sChrome, aChrome, random);
	}

	// read in a brain from the file
	public static AdamBrain makeBrain(String fileName, MersenneTwisterFast random){

		BufferedReader fileReader = null;
		StringTokenizer tokenizer;
		SomaChromosome sChrome = new SomaChromosome();
		AxonChromosome aChrome = new AxonChromosome();
		int numSomas, numAxons;
		int maxSomaNum, maxAxonNum;

		try{
			fileReader = new BufferedReader(new FileReader(fileName));
		}catch(FileNotFoundException e){
			e.printStackTrace();
			return null;
		}

		try{

			tokenizer = new StringTokenizer(fileReader.readLine());
			tokenizer.nextToken();
			numSomas = Integer.parseInt(tokenizer.nextToken());

			tokenizer = new StringTokenizer(fileReader.readLine());
			tokenizer.nextToken();
			numAxons = Integer.parseInt(tokenizer.nextToken());

			for(int i = 0; i < numSomas; i++){
				sChrome.addGene(SomaGene.makeGeneFromString(fileReader.readLine()));
			}

			for(int i = 0; i < numAxons; i++){
				aChrome.addGene(AxonGene.makeGeneFromString(fileReader.readLine()));
			}

			return new AdamBrain(sChrome, aChrome, random);

		}catch(IOException e){
			e.printStackTrace();
			return null;
		}

	}

	// make a completely connected brain with numInputs and numOutputs and one Bias neuron
	public static Brain makeBrain(int numInputs, int numOutputs, MersenneTwisterFast random){

		SomaChromosome sChrome = new SomaChromosome();
		AxonChromosome aChrome = new AxonChromosome();
		SomaGene sGene;
		AxonGene aGene;
		numInputs *=3;

//		sGene = new SomaGene(0, SomaGene.BIAS);
//		sChrome.addGene(sGene);

		for(int i = 0; i < numInputs; i++){
			sGene = new SomaGene(i, SomaGene.INPUT, random.nextInt(SomaGene.MAX_INPUT_USAGE_ID));
			sChrome.addGene(sGene);
		}

		for(int i = 0; i < numOutputs; i++){
			sGene = new SomaGene(numInputs + i, SomaGene.OUTPUT,i);
			sChrome.addGene(sGene);
		}

		for(int i = 0, id = 0; i < numInputs; i++){
			for(int j = 0; j < numOutputs; j++, id++){

				double w = random.nextDouble() * Axon.getMaxWeight();

				if(random.nextBoolean()) w = -w;

				aGene = new AxonGene(id, i, numInputs + j, w);

				aChrome.addGene(aGene);

			}
		}

		AdamBrain brain = new AdamBrain(sChrome, aChrome, random);
		return brain;

	}

	//treats each output node as an independend action
	//also actions no longer have any gradient or power level
	//they are either on or off, this may change in the future
	// the length of actions and out should be the same
	private double[] translateOutput(double[] out){

//		double[] actions = new double[Brain.getNumActions()];
//
//		for(int i = 0; i < actions.length; i++){
//
//			if(out[i]<.5){
//				actions[i] = 0.0;
//			}else{
//				actions[i] = 1.0;
//			}
//
//		}
//return actions;
		return out;
	}

	public double[] activate(double[] inputs){

		this.setInput(inputs);
		this.activate();
		return this.translateOutput(this.getOutput());
	
	}



}
